package com.spring.demo.publicutil.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 线程池任务分解与结果统一收集工具
 */
public class TaskSplitThreadPool {
    // 1. 初始化线程池（可根据业务调整核心线程数、队列等参数）
    private static final ExecutorService THREAD_POOL = new ThreadPoolExecutor(
            4,                  // 核心线程数（CPU核心数建议）
            8,                  // 最大线程数
            60,                 // 空闲线程存活时间
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(20), // 任务队列
            Executors.defaultThreadFactory(), // 线程工厂
            new ThreadPoolExecutor.AbortPolicy() // 任务拒绝策略
    );

    /**
     * 2. 核心方法：分解任务+提交线程池+统一收集结果
     * @param totalTaskNum 子任务总数（示例：分解为N个任务）
     * @return 所有子任务结果的汇总列表
     * @throws InterruptedException 线程中断异常
     * @throws ExecutionException 子任务执行异常
     */
    public static List<Integer> executeAndCollectResult(int totalTaskNum) throws InterruptedException, ExecutionException {
        // 存储所有子任务的Future（用于获取结果）
        List<Future<Integer>> futureList = new ArrayList<>();

        // 3. 请求线程：分解原始任务为多个子任务，提交到线程池
        for (int i = 1; i <= totalTaskNum; i++) {
            int taskParam = i; // 子任务参数（示例：计算1~N的平方）
            // 定义子任务（Callable有返回值，Runnable无返回值，此处用Callable）
            Callable<Integer> subTask = () -> {
                // 子任务业务逻辑（示例：计算参数的平方，模拟耗时操作）
                TimeUnit.MILLISECONDS.sleep(100); // 模拟任务耗时
                int result = taskParam * taskParam;
                System.out.printf("子任务[%d]执行完成，结果：%d，执行线程：%s%n",
                        taskParam, result, Thread.currentThread().getName());
                return result;
            };

            // 提交子任务到线程池，获取Future（跟踪任务状态和结果）
            Future<Integer> future = THREAD_POOL.submit(subTask);
            futureList.add(future);
        }

        // 4. 请求线程：统一收集所有子任务结果
        List<Integer> totalResult = new ArrayList<>();
        for (Future<Integer> future : futureList) {
            // future.get()：阻塞等待子任务完成，获取结果（若子任务异常，此处会抛出ExecutionException）
            Integer subResult = future.get();
            totalResult.add(subResult);
        }

        return totalResult;
    }

    // 5. 测试：模拟请求线程调用
    public static void main(String[] args) {
        try {
            System.out.println("请求线程开始：分解任务并提交线程池");
            // 示例：分解为10个子任务（计算1~10的平方，统一收集结果）
            List<Integer> finalResult = executeAndCollectResult(10);

            // 6. 请求线程获取统一结果并处理
            System.out.println("\n请求线程获取所有子任务结果：" + finalResult);
            // 业务处理（示例：计算所有结果的和）
            int sum = finalResult.stream().mapToInt(Integer::intValue).sum();
            System.out.println("请求线程处理结果：所有子任务结果的和 = " + sum);

        } catch (InterruptedException | ExecutionException e) {
            System.err.println("任务执行异常：" + e.getMessage());
        } finally {
            // 7. 关闭线程池（实际业务中可根据生命周期管理，避免频繁创建/关闭）
            THREAD_POOL.shutdown();
            try {
                // 等待线程池所有任务完成后关闭
                if (!THREAD_POOL.awaitTermination(1, TimeUnit.SECONDS)) {
                    THREAD_POOL.shutdownNow(); // 强制关闭未完成任务
                }
            } catch (InterruptedException e) {
                THREAD_POOL.shutdownNow();
            }
        }
    }
}